#pragma once

#include <algorithm/analytical_model/algorithm/cuda/inter_op/Data.h>
#include <algorithm/analytical_model/algorithm/cuda/inter_op/receiver/Receiver.h>

#include <tuple>

namespace solar::cuda
{
    class CylinderReceiver;
}

namespace solar::cuda::inter_op
{
    class CylinderReceiver : public Receiver
    {
        public:
            virtual ~CylinderReceiver() = default;
            CylinderReceiver(cudaStream_t stream = nullptr);
            void init(float pixel_per_meter_for_receiver) const override;
            void setResolution(float pixel_per_meter_for_receiver) const override;
            [[nodiscard]] auto getFocusCenter(const Float3& heliostat_position) const
                -> Float3 override;
            /**
             * 1) Define equation:
             *      -ray equation: p(t) = (orig - pos) + t * dir     (1)
             *      -cylinder equation: z^2 + m^2 * x^2 = r^2     (r = size.x,  m = 1)    (2)
             * 2) combine equation (1) and (2):
             *      calculate delta: delta = b^2 - 4ac
             *          -if delta >= 0, may have intersection
             *          -if delta < 0, no intersection
             * 3) calculate t and point of intersection
             *          -if t < 0, wrong direction, so remain the positive solution
             *          -if intersect_point.z is not belonging to the range [0, size.z], not
             * effective intersection and return false.
             */
            /// @returns {t, u, v, isIntersected}
            [[nodiscard]] auto intersect(const Float3& orig, const Float3& dir) const
                -> std::tuple<float, float, float, bool>;
    };
} // namespace solar::cuda::inter_op
